import settings from "../utils/settings";
import renderBeaconBeam2 from "../../BeaconBeam";
import { stripRank , drawBoxAtEntity , getcmdfromchat , rayTrace, getItemFromGui, GetAttributesFrom, drawBoxAtPos, sendEssentialNotifications, clearTabCompletionMessage, Vec3iToVec3, urlToFile, getItemSBID, addLore, RemoveEmoji, getPlayerPos, getItemFromNEUREPO, DrawString, getEntityHP, getItemUUID, MessageID, isModLoaded, timedisplay, randomString, getClipboard, copyToClipboard, mouseMove, moveMouseToSlot, getskulltextures, ServerTick } from "../utils/utils";
import { guiMover } from "../utils/gui";
import { location } from "../utils/getLocation";
import { Vec3 } from "../utils/vec3";
import { sack } from "./sack";
import { AddData, SavedData } from "../utils/data";
import ListFix from "../../ListFix";
import eventSettings from "../utils/eventSettings";
import AttributeHighlightSettings from "../utils/AttributeHighlightSettings";

const File = Java.type("java.io.File");


export function sendcoords(location,texts) {
    let channel = "pc";
    let text = texts.split(' ');
    if(["pc","ac","oc","cc","gc"].indexOf(text[0]) != -1) channel = text.shift();
    let message = text.join(' ');
    switch (location) {
        case "LookingAt":
            let pos = {x:0,y:0,z:0}
            if(!Player.lookingAt().toString().includes('minecraft:air')) {
                pos.x = parseInt(Player.lookingAt().getX());
                pos.y = parseInt(Player.lookingAt().getY());
                pos.z = parseInt(Player.lookingAt().getZ());
            } else {
                const block = rayTrace((Client.settings.video.getRenderDistance()*16)^2)
                if(block === null) {ChatLib.chat("§6§l[BZA] §c您没有看向任何物体.");return;}
                pos.x = block.x; pos.y = block.y; pos.z = block.z;
            }
            ChatLib.command(channel + " x: " + pos.x + ", y: " + pos.y + ", z: " + pos.z + (message ? ", " + message : ''))
            break;
        case "Self":
            ChatLib.command(channel + " x: " + parseInt(Player.getX()) +
                ", y: " + parseInt(Player.getY()) + 
                ", z: " + parseInt(Player.getZ()) + 
                (message ? ", " + message : '')
            )
            break;
    }
}

export const serverFinder = {
    island : "",
    cmd : "",
    day : 0,

    /**
     * server finder  自动刷房寻找水晶矿洞房间或地狱或末地
     * @param {string} island 要刷的房  CH (水晶矿洞)  CATA (灾难火山的地狱)  DRAG (有龙的末地)
     * @param {number} day 房间day (一般只有水晶矿洞用得上)
     */
    serverFinder(island,day = 0) {
        switch (island.toLowerCase()) {
            case "ch":
                this.island = "Crystal Hollows";
                this.cmd = "warp ch"
                this.day = day;
                this.worldLoadTrigger.register();
                this.playerInteractTrigger.register();
                ChatLib.chat("§6§l[BZA] §a自动刷房器,启动! 开始寻找 §b" + (day ? day + " §aDay及以上的 §b" : "" ) + "水晶矿洞");
                Client.showTitle("§6§l[BZA] §a自动刷房器,启动!","§a开始寻找 §b" + (day ? day + " §aDay及以上的 §b" : "" ) + "水晶矿洞, §d按下鼠标右键(交互键)关闭自动刷房",0,60,0);
                ChatLib.command((location.island == this.island ? "hub" : this.cmd));
                break;
            case "cata":
            case "crimson":
                this.island = "Crimson Isle";
                this.cmd = "warp crimson";
                this.day = day;
                this.worldLoadTrigger.register();
                this.playerInteractTrigger.register();
                ChatLib.chat("§6§l[BZA] §a自动刷房器,启动! 开始寻找 §b" + (day ? day + " §aDay及以上的 §b" : "" ) + "灾难性火山的地狱房间");
                Client.showTitle("§6§l[BZA] §a自动刷房器,启动!","§a开始寻找 §b" + (day ? day + " §aDay及以上的 §b" : "" ) + "灾难性火山的地狱房间, §d按下鼠标右键(交互键)关闭自动刷房",0,60,0);
                ChatLib.command((location.island == this.island ? "hub" : this.cmd));
                break;
            case "end":
            case "drag":
                this.island = "The End";
                this.cmd = "warp drag";
                this.day = day;
                this.worldLoadTrigger.register();
                this.playerInteractTrigger.register();
                ChatLib.chat("§6§l[BZA] §a自动刷房器,启动! 开始寻找 §b" + (day ? day + " §aDay及以上的 §b" : "" ) + "正在打龙的末地房间");
                Client.showTitle("§6§l[BZA] §a自动刷房器,启动!","§a开始寻找 §b" + (day ? day + " §aDay及以上的 §b" : "" ) + "正在打龙的末地房间, §d按下鼠标右键(交互键)关闭自动刷房",0,60,0);
                ChatLib.command((location.island == this.island ? "hub" : this.cmd));
                break;
            default:
                this.island = "";
                this.cmd = "";
                this.day = 0;
                this.tickTrigger.unregister();
                this.worldLoadTrigger.unregister();
                this.playerInteractTrigger.unregister();
                ChatLib.chat("§6§l[BZA] §e自动刷房器,关闭");
                return;
        }
    },
    tickTrigger : register("tick", () => {
        if(location.island == "") return;   // ↓ 额,不知道为什么只有一次会显示不出来 ↓
        Client.showTitle("§a自动刷房器正在刷房","§e正在准备前往 " + serverFinder.island + " , §d按下鼠标右键(交互键)关闭自动刷房",0,60,0);
        Client.showTitle("§a自动刷房器正在刷房","§e正在准备前往 " + serverFinder.island + " , §d按下鼠标右键(交互键)关闭自动刷房",0,60,0);
        if(location.island == serverFinder.island) {
            if(location.day < serverFinder.day) {
                Client.showTitle(("§b当前房间Day: §e" + location.day + " §7/§a " + serverFinder.day),("§e自动刷房器正在准备离开, §d按下鼠标右键(交互键)关闭自动刷房"),0,60,0);
                setTimeout(() => { if(serverFinder.cmd) ChatLib.command("hub"); }, 3000);
                serverFinder.tickTrigger.unregister();return;
            }
            switch (serverFinder.island) {
                case "Crimson Isle":
                    if(location.volcano.removeFormatting() != "Cataclysmic") {
                        Client.showTitle(("§b当前房间火山状态: " + location.volcano),("§e自动刷房器正在准备离开, §d按下鼠标右键(交互键)关闭自动刷房"),0,60,0);
                        setTimeout(() => { if(serverFinder.cmd) ChatLib.command("hub"); }, 3000);
                        serverFinder.tickTrigger.unregister();return;
                    }
                case "The End":
                    let drag = TabList.getNames().filter(e => e.removeFormatting().startsWith("Dragon: ("));
                    if(drag.length == 0) {
                        Client.showTitle(("§b当前房间没有与末影龙在战斗"),("§e自动刷房器正在准备离开, §d按下鼠标右键(交互键)关闭自动刷房"),0,60,0);
                        setTimeout(() => { if(serverFinder.cmd) ChatLib.command("hub"); }, 3000);
                        serverFinder.tickTrigger.unregister();return;
                    } else {
                        Client.showTitle("§a当前房间正在与 §5" + drag[0].removeFormatting().replace("Dragon Fight: (","").replace(")","") + " Dragon §a战斗","§a自动刷房器已为您找到符合要求的房间",0,100,0);
                    }
            }
            ChatLib.chat("§6§l[BZA] §a自动刷房器已为您找到符合要求的房间");
            if(serverFinder.island != "The End") Client.showTitle((serverFinder.day ? "§b当前房间Day: §a" + location.day + " §7/§a " + serverFinder.day : ""),"§a自动刷房器已为您找到符合要求的房间",0,100,0);
            serverFinder.worldLoadTrigger.unregister(); serverFinder.cmd = ""; serverFinder.day = 0; serverFinder.island = "";
            serverFinder.playerInteractTrigger.unregister();
        } else setTimeout(() => { if(serverFinder.cmd) ChatLib.command(serverFinder.cmd); }, 3000);
        serverFinder.tickTrigger.unregister();
    }).unregister(),
    worldLoadTrigger : register("worldLoad", () => {
        if(serverFinder.island == "") return;
        serverFinder.tickTrigger.register();
    }).unregister(),
    playerInteractTrigger : register("playerInteract",() => {
        if(!location.inSkyblock) return;
        serverFinder.island = "";
        serverFinder.cmd = "";
        serverFinder.day = 0;
        serverFinder.tickTrigger.unregister();
        serverFinder.worldLoadTrigger.unregister();
        serverFinder.playerInteractTrigger.unregister();
        ChatLib.chat("§6§l[BZA] §e自动刷房器,关闭");
        Client.showTitle("§e已关闭自动刷房器","",0,60,0);
    }).unregister()
}


export let misc = {
    getChat : false,
    getActionBar : false,
    AutoTransfer : false,
    lobby : [],
    lobbycheck : false,
    testnum : 0,
    showsound : false,
    NameTag : false,
    jasperFinder : false,

load() {


//get chat (复读机)
register("chat" , (message) => { if(this.getChat) ChatLib.chat(message) }).setCriteria("${message}")

//action bar 复读机
register("actionBar" , (message) => { if(this.getActionBar) ChatLib.chat(message) }).setCriteria("${message}")

//autoTransfer
register("chat", (p1, p2) => {
	if (stripRank(p1) == Player.getName() && this.AutoTransfer) {
		ChatLib.command(`p transfer ${stripRank(p2)}`)
	}
}).setChatCriteria(/The party was transferred to (.+) by (.+)/)

register("chat", (p2, message1, p1) => {
	if (stripRank(p2) == Player.getName() && this.AutoTransfer) {
		ChatLib.command(`p promote ${stripRank(p1)}`)
	}
}).setChatCriteria(/(.+)( has promoted |将组队移交给了|已将)(.+)( to Party Leader||提拔为组队队长，(.+)现在为组队管理员)/)

//看看这个房是不是刚刚来过
register("chat", (server) => {
    setTimeout(() => {
        if(server.includes(' ') || !this.lobbycheck || !location.inSkyblock) return;
        if(this.lobby.indexOf(server) != -1) sendEssentialNotifications("§eLobby Check","§6进入了 §7" + server + "\n§4这房刚刚来过了~",10.0);
        else this.lobby.push(server);
    }, 500);
}).setChatCriteria("You are currently connected to server ${server}");

//显示声音的播放
register("soundPlay", (pos,name,vol,pit,cate,event) => {
    if(vol == 0) return;
    if(this.showsound) new TextComponent(
        `§6§l[BZA] §e声音播放§7:§b ${name} §e分类§7:§b ${cate} §e音量§7:§b ${vol} §e音调§7:§b ${pit}`
    ).setHover("show_text",`§bpos§7: §5${pos.toString()}`).chat();
})

//NameTag
register("renderWorld", () => {
    if (!this.NameTag || !location.inSkyblock) return;
    World.getAllPlayers().filter(e => !e.isDead() && e.getName() != Player.getName() && !e.getName().includes(' ') && parseInt(getEntityHP(e).maxhp) != 20).forEach(e => {
        let distance = e.distanceTo(Player.getPlayer());
        let textDistance = Math.max(Math.min(distance,100),5);
        Tessellator.drawString("§d§k|§r " + (isModLoaded("skyblockaddons") ? "§Z" : "§b") + e.getName() + " §e(" + parseInt(distance) + "m)§r §d§k|",e.getX(),e.getY() + 1,e.getZ(),0,true,textDistance/500,false);
        Tessellator.drawString("§bHolding§7:§r " + (e.getEntity().func_71124_b(0) ? e.getEntity().func_71124_b(0).func_82833_r() : "§7null"),e.getX(),e.getY() + 1 - textDistance/50,e.getZ(),0,true,textDistance/500,false);
    })
})

}}

//jasperFinder
const MCNBTTagCompound = Java.type("net.minecraft.nbt.NBTTagCompound");
const jasperFinder = {
    blocks : [],
    goldendragon : {
        pos : {x:0,y:0,z:0},
        eggs : 0,
    },

    getSkullTextures(skull) {
        try {
            let nbt = new MCNBTTagCompound();
            skull.tileEntity.func_145841_b(nbt);
            let skullstring = new NBTTagCompound(nbt);
            return skullstring?.toObject()?.Owner?.Properties?.textures[0]?.Value;
        } catch (error) { return undefined; }
    }
}

register(net.minecraftforge.event.world.ChunkEvent.Load, event => {
    if(misc.jasperFinder && location.inSkyblock && location.island == "Crystal Hollows") try {
        let chuck = new Chunk(event.getChunk());
        setTimeout(() => {
            for (let x = chuck.getMinBlockX(); x < chuck.getMinBlockX() + 16; x++) {
                for (let z = chuck.getMinBlockZ(); z < chuck.getMinBlockZ() + 16; z++) {
                    if(x > 463 && x < 563 && z > 463 && z < 563) continue;
                    for (let y = 31; y < 189; y++) {
                        let block = World.getBlockAt(x,y,z);
                        let blockName = block.getType().getRegistryName();
                        if(blockName == "minecraft:air" || blockName == "minecraft:bedrock") continue;
                        if((blockName == "minecraft:stained_glass_pane" || blockName == "minecraft:stained_glass") && block.getMetadata() == 2) {
                            jasperFinder.blocks.push({x:x,y:y,z:z});
                        };
                    }
                }
            }
        }, 10);
    } catch (error) {}
})

register("step", () => {
    if(misc.jasperFinder && location.inSkyblock && location.island == "Crystal Hollows") {
        if(jasperFinder.goldendragon.eggs == 0) World.getAllTileEntitiesOfType(net.minecraft.tileentity.TileEntitySkull).filter(e => jasperFinder.getSkullTextures(e) == "ewogICJ0aW1lc3RhbXAiIDogMTYyMDM1MDExNzgyMiwKICAicHJvZmlsZUlkIiA6ICJkMGI4MjE1OThmMTE0NzI1ODBmNmNiZTliOGUxYmU3MCIsCiAgInByb2ZpbGVOYW1lIiA6ICJqYmFydHl5IiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzExM2JkZjJkMmIwMDYwNTYwNjgyNmRmNzZlMjExZWEyODhhYTA1MGVkYzlkNzFjYjA5OTg2YzQ4OGNhMDQxMWMiLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ==").forEach(e => {
            jasperFinder.goldendragon.eggs++;
            jasperFinder.goldendragon.pos = {x:e.getX(),y:e.getY(),z:e.getZ()};
            World.playSound("note.harp",1,1);
            Client.showTitle("§a" + jasperFinder.goldendragon.eggs + " Egg" + (jasperFinder.goldendragon.eggs > 1 ? "s" : ""),"§6Golden Dragon",0,80,20);
        });
        setTimeout(() => {
            jasperFinder.blocks = jasperFinder.blocks.filter((block, index, self) =>
                index === self.findIndex(b => b.x === block.x && b.y === block.y && b.z === block.z)
            );
        }, 5);
    }
}).setDelay(1)

register("renderWorld", () => {
    if(misc.jasperFinder && location.inSkyblock && location.island == "Crystal Hollows") {
        jasperFinder.blocks.forEach(e => { drawBoxAtPos(e.x,e.y,e.z,0,0.5,0,0.5,1,1,1,2,true); })
        if(jasperFinder.goldendragon.eggs > 0) {
            let pos = jasperFinder.goldendragon.pos;
            Tessellator.drawString("§6Golden Dragon §7- §a" + jasperFinder.goldendragon.eggs + " Egg" + (jasperFinder.goldendragon.eggs > 1 ? "s" : "") + " §6(" + parseInt(getPlayerPos().distance(new Vec3(pos.x,pos.y,pos.z))) + "m)",Math.floor(pos.x)+0.5,Math.floor(pos.y)+0.5,Math.floor(pos.z)+0.5,0,true,0.8,true);
        }
    }
})
register("worldLoad", () => { 
    jasperFinder.blocks = [];
    jasperFinder.goldendragon = {pos:{x:0,y:0,z:0},eggs:0};
})


//收发包显示
export const showPacket = {
    getPacketSent : false,
    getPacketReceived : false,
    packetSendIgnore : [],
    packetReceiveIgnore : [],
    togglePacketSent(ignore = -1) {
        if(ignore != -1) {
            this.packetSendIgnore.push(ignore);
            return;
        }
        this.getPacketSent = !this.getPacketSent;
        this.packetSendIgnore = [];
        ChatLib.chat(showPacket.getPacketSent ? "§6§l[BZA] §b§lget packet sent §a§lON" : "§6§l[BZA] §b§lget packet sent §4§lOFF");
    },
    togglePacketReceived(ignore = -1) {
        if(ignore != -1) {
            this.packetReceiveIgnore.push(ignore);
            return;
        }
        this.getPacketReceived = !this.getPacketReceived;
        this.packetReceiveIgnore = [];
        ChatLib.chat(showPacket.getPacketReceived ? "§6§l[BZA] §b§lget packet received §a§lON" : "§6§l[BZA] §b§lget packet received §4§lOFF");
    }
}

register("packetSent", (packet, event) => {
    if(!showPacket.getPacketSent) return;
    let packetname = packet.toString().replace(/@[0-9a-zA-Z]+/i,"");
    showPacket.packetSendIgnore.filter(e => packetname.includes(e)).length == 0 && ChatLib.chat(packetname);
})
register("packetReceived", (packet, event) => {
    if(!showPacket.getPacketReceived) return;
    let packetname = packet.toString().replace(/@[0-9a-zA-Z]+/i,"");
    showPacket.packetReceiveIgnore.filter(e => packetname.includes(e)).length == 0 && ChatLib.chat(packetname);
})


//在Skyblock里取消放置末影珍珠
register("playerInteract", (action,pos,event) => { settings.CancelPlaceEnderPearl && location.inSkyblock && action.toString() == "RIGHT_CLICK_BLOCK" && Player.getHeldItem() && getItemSBID(Player.getHeldItem()) == "ENDER_PEARL" && cancel(event); })


//double lobby
register("command",()=>{
    ChatLib.command("lobby");
    setTimeout(() => {
        ChatLib.command("lobby");
    }, 300);
}).setName("ll")

//double lobby when not in skyblock
register("chat",()=>{
    if(!settings.Doublelobby) return;
    if(!location.inSkyblock) ChatLib.command(`lobby`);
}).setChatCriteria("Are you sure? Type /lobby again if you really want to quit.");

//auto selected language
AddData("hyplang","")
register("chat",(lang)=>{
    SavedData.hyplang = lang;
}).setChatCriteria("Selected language: ${lang}")

register("chat",(lang)=>{
    SavedData.hyplang = lang;
}).setChatCriteria("已选择语言：${lang}")

register("chat",(lang)=>{
    SavedData.hyplang = lang;
}).setChatCriteria("We automatically changed your language to ${lang}.")

register("chat",(server)=>{
    SavedData.hyplang = "简体中文";
}).setChatCriteria("正在前往${server}...")

register("worldLoad", () => {
    if(!settings.autolanginsb || SavedData.hyplang == "English") return;
    setTimeout(() => { if(location.inSkyblock) ChatLib.command(`setlanguage ENGLISH`); ;}, 1000);
});


//No more "There are blocks in the way!"
register("chat", (event) => {
    if(settings.BlocksInTheWay) cancel(event);
}).setCriteria("There are blocks in the way!")

//kill combo
let KillComboColor = "§r";
let KillComboInEdit = false;
let KillComboDisplay = new Display()
    .setShouldRender(false)
    .setBackground('full')
    .setBackgroundColor(Renderer.color(0,0,0,0))
    .setRenderLoc(guiMover.settings.KillCombo.x, guiMover.settings.KillCombo.y);

register("renderOverlay", () =>{
    if(guiMover.gui.isOpen()){
        KillComboInEdit = true;
        if(!settings.KillCombo) return;
        KillComboDisplay.setShouldRender(true)
        KillComboDisplay.setRenderLoc(guiMover.settings.KillCombo.x, guiMover.settings.KillCombo.y);
        guiMover.settings.KillCombo.s = 1.0;
        KillComboDisplay.setLine(0, new DisplayLine("§6§l+30 Kill Combo").setShadow(true))
        KillComboDisplay.setLine(1, new DisplayLine("§b+9✯ Magic Find").setShadow(true))
        KillComboDisplay.setLine(2, new DisplayLine("§8+§620 §7coins per kill").setShadow(true))
        KillComboDisplay.setLine(3, new DisplayLine("§3+15☯ Combat Wisdom").setShadow(true))
    }else if(KillComboInEdit){
        KillComboDisplay.setLine(0, new DisplayLine("").setShadow(true))
        KillComboDisplay.setLine(1, new DisplayLine("").setShadow(true))
        KillComboDisplay.setLine(2, new DisplayLine("").setShadow(true))
        KillComboDisplay.setLine(3, new DisplayLine("").setShadow(true))
        KillComboDisplay.setShouldRender(false)
        KillComboInEdit = false;
    }
})
register("chat", (kills,buff,event) => {
    if(!settings.KillCombo) return;
    cancel(event)
        if(kills == 5 || kills == 10){KillComboColor = "§a"}else if(kills == 15){KillComboColor = "§9"}else if(kills == 20 || kills == 25){KillComboColor = "§5"}else if(kills == 30){KillComboColor = "§6"}
        KillComboDisplay.setShouldRender(true)
        KillComboDisplay.setLine(0, new DisplayLine(KillComboColor + "§l+" + kills + " Kill Combo").setShadow(true))
        if(kills == 5){
            KillComboDisplay.setLine(1, new DisplayLine("§b+3✯ Magic Find").setShadow(true))
        }else if(kills == 10){
            KillComboDisplay.setLine(2, new DisplayLine("§8+§610 §7coins per kill").setShadow(true))
        }else if(kills == 15){
            KillComboDisplay.setLine(1, new DisplayLine("§b+6✯ Magic Find").setShadow(true))
        }else if(kills == 20){
            KillComboDisplay.setLine(3, new DisplayLine("§3+15☯ Combat Wisdom").setShadow(true))
        }else if(kills == 25){
            KillComboDisplay.setLine(1, new DisplayLine("§b+9✯ Magic Find").setShadow(true))
        }else if(kills == 30){
            KillComboDisplay.setLine(2, new DisplayLine("§8+§620 §7coins per kill").setShadow(true))
        }
}).setCriteria("+${kills} Kill Combo +${buff}")

register("chat", (kills,event) => {
    if(!settings.KillCombo || kills <= 30) return;
    cancel(event);
    KillComboDisplay.setLine(0, new DisplayLine(KillComboColor + "§l+" + kills + " Kill Combo").setShadow(true))
}).setCriteria("+${kills} Kill Combo")

register("chat", (kills,event) => {
    if(!settings.KillCombo) return;
    KillComboDisplay.setLine(0, new DisplayLine("").setShadow(true))
    KillComboDisplay.setLine(1, new DisplayLine("").setShadow(true))
    KillComboDisplay.setLine(2, new DisplayLine("").setShadow(true))
    KillComboDisplay.setLine(3, new DisplayLine("").setShadow(true))
    KillComboDisplay.setShouldRender(false)
}).setCriteria("Your Kill Combo has expired! You reached a ${kills} Kill Combo!")

register("worldLoad", () => {
    KillComboDisplay.setLine(0, new DisplayLine("").setShadow(true))
    KillComboDisplay.setLine(1, new DisplayLine("").setShadow(true))
    KillComboDisplay.setLine(2, new DisplayLine("").setShadow(true))
    KillComboDisplay.setLine(3, new DisplayLine("").setShadow(true))
    KillComboDisplay.setShouldRender(false)
})


//Trevor The Trapper 打电话后自动接任务
register("chat",(newLine,event)=>{
    if(!settings.trapper) return;
    let cmd = getcmdfromchat(event,"[YES]")
    if(cmd){ChatLib.say(cmd)}
}).setCriteria("${newLine}Accept the trapper's task to hunt the animal?->newLine<-Click an option: [YES] - [NO]")


//creeper?
register("step", () => {
    if(!settings.creeper || !location.inSkyblock) return;
    if(
        (location.island == "Deep Caverns" && location.location == "Gunpowder Mines" && settings.creeper == 2) || 
        (location.island == "Dwarven Mines" && location.location == "The Mist")
    ) {
        World.getAllEntitiesOfType(net.minecraft.entity.monster.EntityCreeper).forEach(e=>{
            e.getEntity().func_82142_c(false);  //setInvisible
        })
    }
}).setDelay(1)

//A Vanquisher is spawning nearby!
register("chat",() => {
    if(settings.Vanquisher && location.island == "Crimson Isle"){
        ChatLib.say(
            settings.VanquisherMessage
            .replace(/%x%/g,parseInt(Player.getRenderX()))
            .replace(/%y%/g,parseInt(Player.getRenderY()))
            .replace(/%z%/g,parseInt(Player.getRenderZ()))
            .replace(/%location%/g,location.location)
            .replace(/%server%/g,location.server)
            .replace(/%random%/g,randomString(8))
            );
    }
}).setChatCriteria("A Vanquisher is spawning nearby!")

//九点报时
register("step", () => {
    if(settings.time9pm && location.inSkyblock && Scoreboard.getLines().filter(e => e.toString().includes("9:00pm")).length == 1) {
        World.playSound("random.levelup",1,1.4);
        Client.showTitle("","§b现在是SB时间晚上 §6§l9 §b点整",0,80,20);
    };
}).setDelay(8)

/**
 * 在物品下面写时间戳(生产日期,一般都是)
 * @param {Item} item 
 * @returns 
 */
function addTimestampToItem(item) {
    try {
        let timestamp = item?.getNBT()?.getCompoundTag("tag")?.getCompoundTag("ExtraAttributes")?.getLong("timestamp");
        if(!timestamp) return;
        let time = new Date(timestamp);
        let TimeString = "";
        switch (settings.ItemTimeZone) {
            case 0:
                TimeString = time.toLocaleString();
                break;
            case 1:
                TimeString = time.getUTCFullYear() + '-' + (time.getUTCMonth() + 1) + '-' + time.getUTCDate() + ' ' + time.getUTCHours() + ':' + (time.getUTCMinutes() < 10 ? '0' + time.getUTCMinutes() : time.getUTCMinutes()) + ':' + (time.getUTCSeconds() < 10 ? '0' + time.getUTCSeconds() : time.getUTCSeconds()) + ' UTC';
                break;
            case 2:
                TimeString = time.getFullYear() + '-' + (time.getMonth() + 1) + '-' + time.getDate() + ' ' + time.getHours() + ':' + (time.getMinutes() < 10 ? '0' + time.getMinutes() : time.getMinutes()) + ':' + (time.getSeconds() < 10 ? '0' + time.getSeconds() : time.getSeconds()) + ' UTC' + ((0 - new Date().getTimezoneOffset() / 60) >= 0 ? "+" : "-") + (0 - new Date().getTimezoneOffset() / 60);
                break;
        }
        addLore(item,`§r§7TimeStamp: ${TimeString}`);
    } catch (error) {}
}
function addSkyblockUUID(item) {
    try {
        let uuid = getItemUUID(item);
        if(!uuid) return;
        addLore(item,"§8uuid: " + uuid);
    } catch (error) { }
}
let guiOpen = false;
register("guiOpened", () => { guiOpen = true; })
register("guiClosed", () => { guiOpen = false; })
register("renderItemIntoGui", (item,x,y,event) => {
    if(!Player.getContainer() || (Player.getContainer().getClassName() == "ContainerPlayer" && !guiOpen)) return;
    if(settings.ItemTimeStamp == 1) addTimestampToItem(item);
    if(settings.ItemSkyblockUUID == 1) addSkyblockUUID(item);
})

register(net.minecraftforge.event.entity.player.ItemTooltipEvent, event => {
    let item = new Item(event.itemStack);
    if(settings.ItemSkyblockUUID == 2) {
        try {
            let uuid = getItemUUID(item);
            if(uuid) ListFix.add(event,"toolTip","§8uuid: " + uuid);
        } catch (error) {}
    }
    if(settings.ItemTimeStamp == 2) {
        try {
            let timestamp = item?.getNBT()?.getCompoundTag("tag")?.getCompoundTag("ExtraAttributes")?.getLong("timestamp");
            if(timestamp) {
                let time = new Date(timestamp);
                let TimeString = "§r§8TimeStamp: ";
                switch (settings.ItemTimeZone) {
                    case 0:
                        TimeString += time.toLocaleString();
                        break;
                    case 1:
                        TimeString += time.getUTCFullYear() + '-' + (time.getUTCMonth() + 1) + '-' + time.getUTCDate() + ' ' + time.getUTCHours() + ':' + (time.getUTCMinutes() < 10 ? '0' + time.getUTCMinutes() : time.getUTCMinutes()) + ':' + (time.getUTCSeconds() < 10 ? '0' + time.getUTCSeconds() : time.getUTCSeconds()) + ' UTC';
                        break;
                    case 2:
                        TimeString += time.getFullYear() + '-' + (time.getMonth() + 1) + '-' + time.getDate() + ' ' + time.getHours() + ':' + (time.getMinutes() < 10 ? '0' + time.getMinutes() : time.getMinutes()) + ':' + (time.getSeconds() < 10 ? '0' + time.getSeconds() : time.getSeconds()) + ' UTC' + ((0 - new Date().getTimezoneOffset() / 60) >= 0 ? "+" : "-") + (0 - new Date().getTimezoneOffset() / 60);
                        break;
                }
                ListFix.add(event,"toolTip",TimeString);
            }
        } catch (error) {}
    }
})


//个人压缩机和删除器预览
const mc = Client.getMinecraft();
const Mouse = Java.type("org.lwjgl.input.Mouse");
const slotPNG = Image.fromAsset("slot.png");
register(net.minecraftforge.event.entity.player.ItemTooltipEvent, event => {
    try {
        if(!settings.PersonalCompact) return;
        let PersonalCompactItems = [];
        const item = new Item(event.itemStack);
        if(!item) return;
        const SBID = getItemSBID(item);
        if(!SBID) return;
        if(!SBID.startsWith("PERSONAL_COMPACTOR_") && !SBID.startsWith("PERSONAL_DELETOR_")) return;
        const tag = item.getNBT().getCompoundTag("tag").getCompoundTag("ExtraAttributes").toObject();
        for (let key in tag) {
            if(key.startsWith("personal_")) PersonalCompactItems.push(tag[key]);
        }
        const str = "§b状态§7: " + (tag.PERSONAL_DELETOR_ACTIVE ? "§a已开启" : "§e已关闭") + (PersonalCompactItems.length == 0 ? " §7,§c里面空空如也" : " §7,§b物品" + (PersonalCompactItems.length == 1 ? "§7: §a" + PersonalCompactItems[0].replace(/_/g,' ').toLowerCase() : "列表§7: \n§a " + PersonalCompactItems.join('\n §a').replace(/_/g,' ').toLowerCase()));
        str.split("\n").forEach(e => ListFix.add(event,"toolTip",e));

        if(!FileLib.isDirectory("./config/notenoughupdates/repo/items")) return;
        let x = Mouse.getX() / Renderer.screen.getScale() - 8;
        let y = Renderer.screen.getHeight() - Mouse.getY() / Renderer.screen.getScale() + 12;
        let items = [];
        PersonalCompactItems.forEach(e => {
            let itemStack = getItemFromNEUREPO(e);
            if(itemStack) items.push(new Item(itemStack));
        });
        if(items.length === 0) return;
        items.forEach(e => {
            e.draw(-16,-16);
            Renderer.translate(0,0,300);
            slotPNG.draw(x,y,18,18);
            Renderer.translate(0,0,50);
            e.draw(x+1,y+1);
            y+= 20;
        })
    } catch (error) {}
})

//在地狱套装层数叠满以后把活塞声音给取消了
let mutePiston = false;
register("actionBar",(message) => {
    if(!location.inSkyblock || !settings.mutecrimsonarmor) return;
    if(message.includes("10⁑") || message.includes("10ᝐ") || message.includes("10Ѫ")) mutePiston = true; else mutePiston = false;
}).setCriteria("${message}")

register("soundPlay" , (position,name,vol,pitch,category,event) => {
    if(!location.inSkyblock || !settings.mutecrimsonarmor || !mutePiston) return;
    if(name == "tile.piston.in" || name == "tile.piston.out") cancel(event);
})

//在铁砧页面把物品的名字里的&改成§ (这好像不止会影响预览的,如果你是正在修改物品名字的话)
register("itemTooltip",(lore,item)=>{
    if(Player.getContainer() && Player.getContainer().getClassName() == "ContainerRepair" && item.getID() == 339 && (item.getName().includes("&z") || item.getName().includes("&Z"))) item.setName(item.getName().replace(/&[zZ]/,'§z'));
})

//显示Rift城堡里没拆的血柱
let Effigies = [];
let EffigiesH = 0;
const EffigiesPos = [{x:150,y:73,z:95},{x:193,y:87,z:119},{x:235,y:104,z:147},{x:293,y:90,z:134},{x:262,y:93,z:94},{x:240,y:123,z:118}];
register("step",()=>{ EffigiesH = 6; setTimeout(() => { EffigiesH = 4; }, 250); setTimeout(() => { EffigiesH = 2; }, 500); setTimeout(() => { EffigiesH = 0; }, 750); }).setDelay(1);
register("tick", () => {
    if(!settings.ShowEffigies || !location.inSkyblock || location.island != "The Rift") return;
    Effigies = [];
    const EffigiesOnScoreboard = Scoreboard.getLines().filter(e => e.toString() && e.toString().startsWith("Effigies: ") && e.toString().includes("⧯"));
    if(EffigiesOnScoreboard.length != 1) return;
    RemoveEmoji(EffigiesOnScoreboard[0].toString()).replace("Effigies: §","").split('§').forEach((e,i) => {
        if(e == "7") Effigies.push(i);
    });
})
register("renderWorld",() => {
    if(!settings.ShowEffigies || !location.inSkyblock || location.island != "The Rift") return;
    if(Effigies.length == 0) return;
    Effigies.forEach(e => {
        renderBeaconBeam2(EffigiesPos[e].x,EffigiesPos[e].y,EffigiesPos[e].z,1,0,0,1,true);
        drawBoxAtPos(EffigiesPos[e].x,EffigiesPos[e].y + EffigiesH,EffigiesPos[e].z,1,0.4,1,1,1,1,1,4,false);
        Tessellator.drawString("§e(§c" + Math.floor(getPlayerPos().distance(new Vec3(EffigiesPos[e].x,EffigiesPos[e].y,EffigiesPos[e].z))) + "m§e)",EffigiesPos[e].x+0.5,EffigiesPos[e].y+0.5,EffigiesPos[e].z+0.5,0,true,0.08,false);
    })
})

//Your Explosive Bow is ineffective!
register("chat" , (event) => {
    if(getItemSBID(Player.getHeldItem()) == "EXPLOSIVE_BOW") cancel(event);
}).setCriteria("Your Superboom TNT is ineffective!")

//显示物品Attribute词条
let AttName = {arachno:"§cAC",arachno_resistance:"§aAR",attack_speed:"§eAS",blazing:"§cBL",blazing_fortune:"§bBF",blazing_resistance:"§aBR",breeze:"§bBR",combo:"§bCO",deadeye:"§cDE",dominance:"§cDO",double_hook:"§bDH",elite:"§cEL",ender:"§cEN",ender_resistance:"§aER",experience:"§bEX",fortitude:"§aFO",fisherman:"§bFM",fishing_experience:"§bFE",fishing_speed:"§bFS",hunter:"§bHT",ignition:"§cIG",infection:"§cIN",life_recovery:"§dLS",life_regeneration:"§cLR",lifeline:"§cLL",magic_find:"§bMF",mana_pool:"§bMP",mana_regeneration:"§bMR",mana_steal:"§bMS",midas_touch:"§eMT",speed:"§fSP",trophy_hunter:"§6TH",undead:"§cUN",undead_resistance:"§aUR",veteran:"§bVE",mending:"§cVI",warrior:"§cWA"}
try {
    Object.assign(AttName,JSON.parse(FileLib.read("./config/ChatTriggers/modules/BabyzombieAddons/config/AttName.json")));
} catch (error) {}

register("renderItemOverlayIntoGui",DrawAttributes)
function DrawAttributes(item,x,y,event) {
    if(!location.inSkyblock || !settings.ShowAttUnderItem) return;
    let Attributes = GetAttributesFrom(item);
    if(!Attributes) return;
    let att = new Array();
    for (let at in Attributes) {
        att.push(AttName[at],Attributes[at])
    }        
    Renderer.translate(0,0,260);
    if(att.length > 2) {
        att = [att[0],att[2]];
        Renderer.scale(0.7);
        Renderer.drawString(att.join(' '),x / 0.7 + 1,y / 0.7 - 6,true);
    } else {
        Renderer.scale(0.8);
        Renderer.drawString(att.join(' '),x / 0.8 + 1,y / 0.8 - 6,true);
    }
}

function replaceAttributeName(attName) { return attName.replace(/_/g,' ').replace('mending','vitality'); }
export function SetAttName(att="",name="") {
    if(att == "" || AttName[att] === undefined) {
        new TextComponent(`§1§m                                                                  `).setHover("show_text","§6这是一条分割线").chat();
        for (let att in AttName) {
            new TextComponent(replaceAttributeName(att) + " §7:§r " + AttName[att]).setClick("suggest_command","/babyzombieaddons attname " + att + " " + AttName[att]).setHover("show_text","&b点击开始修改 &e" + replaceAttributeName(att) + " &b的显示文本").chat();
        }
        new TextComponent(`§1§m                                                                  `).setHover("show_text","§6这也是一条分割线").chat();
    } else {
        AttName[att] = name;
        FileLib.write("./config/ChatTriggers/modules/BabyzombieAddons/config/AttName.json",JSON.stringify(AttName,null,4),true);
        new TextComponent("§6§l[BZA] §a已将 §b" + replaceAttributeName(att) + " §r§a的词条显示改为了 §7:§r " + name).setClick("suggest_command","/babyzombieaddons attname " + att + " " + name).setHover("show_text","&e不满意? 继续改!").chat();
    }
}


//cake
const cakes = {
    "10❤ Health" : 2,
    "3❈ Defense" : 4,
    "2❁ Strength" : 6,
    "10✦ Speed" : 8,
    "5✎ Intelligence" : 10,
    "2⫽ Ferocity" : 12,
    "1♨ Vitality" : 14,
    "1❂ True Defense" : 16,
    "1α Sea Creature Chance" : 18,
    "1✯ Magic Find" : 20,
    "1♣ Pet Luck" : 22,
    "1❄ Cold Resistance" : 24,
    "10ф Rift Time" : 26,
    "5☘ Mining Fortune" : 28,
    "5☘ Farming Fortune" : 30,
    "5☘ Foraging Fortune" : 32
};
let CakeMessage = new Message(
    "§f§m                                        §r",
    "\n§c❤ Health   ", "§c✘",
    "\n§a❈ Defense   ", "§c✘",
    "\n§c❁ Strength   ", "§c✘",
    "\n§f✦ Speed   ", "§c✘",
    "\n§b✎ Intelligence   ", "§c✘",
    "\n§c⫽ Ferocity   ", "§c✘",
    "\n§4♨ Vitality   ", "§c✘",
    "\n§f❂ True Defense   ", "§c✘",
    "\n§3α Sea Creature Chance   ", "§c✘",
    "\n§b✯ Magic Find   ", "§c✘",
    "\n§d♣ Pet Luck   ", "§c✘",
    "\n§b❄ Cold Resistance   ", "§c✘",
    "\n§aф Rift Time   ", "§c✘",
    "\n§6☘ Mining Fortune   ", "§c✘",
    "\n§6☘ Farming Fortune   ", "§c✘",
    "\n§6☘ Foraging Fortune   ", "§c✘",
    "\n§f§m                                        §r",
).setChatLineId(MessageID.Cake);

register("chat", (message,event) => {
    if(!settings.CakeMessage || !location.inSkyblock || location.island != "Private Island") return;
    if(!message.endsWith(" for 48 hours!") || !(message.startsWith("Yum! You gain +") || message.startsWith("Big Yum! You refresh +"))) return;
    try {
        const cake = message.replace("Yum! You gain +","").replace("Big Yum! You refresh +","").replace(" for 48 hours!","");
        CakeMessage.setTextComponent(cakes[cake],"§a✔");
        if(CakeMessage.getUnformattedText().includes("✘")) ChatLib.chat(CakeMessage);
         else new Message("§6§l[BZA] §a您已经吃过了所有的16种蛋糕!§r").setChatLineId(MessageID.Cake).chat();
        cancel(event);
    } catch (error) {}
}).setCriteria("${message}")

//bz getfromsacks
let TryToGet = false;
register("guiOpened" , () => { TryToGet = false; })
register("guiMouseClick" , (x,y,button,gui,event) => {
    if(!settings.bzGetfromsacks || TryToGet) return;
    let item = getItemFromGui(gui);
    if(!item || item.getName().removeFormatting() != "Create Sell Offer") return;
    let lore = item.getLore().filter(e => e != "");
    if(lore.filter(e => e.removeFormatting() == "None in inventory!").length == 0) return;
    cancel(event);
    ChatLib.command('getfromsacks ' + lore[1].removeFormatting() + ' 2304');
    TryToGet = true;
    if(settings.bzGetfromsacks == 1.0) return;
    setTimeout(() => { Player.getContainer().click(gui.getSlotUnderMouse().field_75222_d,false,"LEFT"); }, 500);
})

//duke X
let dukePos = [];
register("tick", () => {
    dukePos = [];
    if(!settings.dukeX || location.island != "Crimson Isle" || location.location != "The Dukedom") return;
    const dukeX = World.getAllEntitiesOfType(net.minecraft.entity.item.EntityArmorStand).filter(e => e && e.getName().removeFormatting().startsWith("﴾ [Lv200] Barbarian Duke X "))[0];
    if(dukeX) dukePos = [dukeX.getX(),dukeX.getY(),dukeX.getZ()];
})
register("renderWorld", () => {
    if(!dukePos.length) return;
    Tessellator.drawString((dukePos[1] > 115.98 ? "§7↑ §aDuke §7↑" : "§7↓ §eDuke §7↓"),dukePos[0],115.98,dukePos[2],0,true,0.05,false);
})

//Unknown command. Type "/help" for help. ('uhfdsolguhkjdjfhgkjhdfdlgkjhldkjhlkjhsldkjfhldshkjf')
register("chat", (event) => {
    cancel(event);
}).setCriteria(`Unknown command. Type "/help" for help. ('uhfdsolguhkjdjfhgkjhdfdlgkjhldkjhlkjhsldkjfhldshkjf')`)

//凋零盾计时
function isHype(item) {
    if(!item) return false;
    if(/*item.getID() == 267 && */["NECRON_BLADE","HYPERION","ASTRAEA","SCYLLA","VALKYRIE"].indexOf(getItemSBID(item)) != -1) return true;
    return false;
}

let HypeClick = 0;
let WitherShield = 0;
let ShieldReady = 0;
let WitherImpart = false;
register("soundPlay", (pos,name,vol,pit,cate,event) => {
    if(!location.inSkyblock || !settings.WitherShield || HypeClick < ServerTick.getTime() || name != "mob.zombie.remedy" ) return;
    WitherShield = ServerTick.getTime() + (WitherImpart ? 5000 : 10000);
    HypeClick = 0;
})

register("playerInteract", (action,pos,event) => {
    if(!location.inSkyblock || !settings.WitherShield || (WitherShield != 0 && WitherShield - ServerTick.getTime() > 1000)) return
    if(!isHype(Player.getHeldItem())) return;
    let scroll = Player.getHeldItem().getNBT().getCompoundTag("tag")?.getCompoundTag("ExtraAttributes").toObject().ability_scroll
    if(!scroll || scroll.indexOf("WITHER_SHIELD_SCROLL") == -1) return;
    if(scroll.length == 3) WitherImpart = true; else WitherImpart = false;
    HypeClick = ServerTick.getTime() + 500;
})

register("renderOverlay", () => {
    if(!settings.WitherShield) return;
    if(guiMover.gui.isOpen()) {
        DrawString("§6Shield: 1.145s", guiMover.settings.WitherShield.x , guiMover.settings.WitherShield.y , guiMover.settings.WitherShield.s , true);
        return;
    }
    if(!location.inSkyblock) return;
    if(WitherShield != 0 && WitherShield < ServerTick.getTime()) {
        WitherShield = 0;
        ShieldReady = ServerTick.getTime() + 3000;
    }
    switch (settings.WitherShield) {
        case 1:
            if(WitherShield == 0) return;
            break;
        case 2:
            if(WitherShield == 0 && ShieldReady - ServerTick.getTime() < 0) return;
            break;
        case 3:
            if(!ShieldReady) return;
            break;
    }
    DrawString("§6Shield: " + (WitherShield - ServerTick.getTime() > 0 ? timedisplay(WitherShield - ServerTick.getTime()) : "§aReady!"), guiMover.settings.WitherShield.x , guiMover.settings.WitherShield.y , guiMover.settings.WitherShield.s , true);
})

register("step", () => {
    if(!location.inSkyblock || settings.WitherShield != 3) return;
    if(Player.getInventory().getItems().filter(e => e && isHype(e)).length > 0) ShieldReady = 1; else ShieldReady = 0;
}).setDelay(1)

register("worldLoad", () => {
    HypeClick = 0;
    WitherShield = 0;
    ShieldReady = 0;
    WitherImpart = false;
})

//hide wither impart
function isHeldHype(player) {
    if(!player.getEntity().func_71124_b(0)) return false;
    const item = new Item(player.getEntity().func_71124_b(0));
    if(!item) return false;
    return isHype(item);
}
let hypeUser = [];
register("tick", () => {
    if(!settings.hideHyperion || !location.inSkyblock) return;
    hypeUser = World.getAllPlayers().filter(e => isHeldHype(e));
})
register("spawnParticle", (particle,type,event) => {
    if(!settings.hideHyperion || !location.inSkyblock) return;
    if(hypeUser.length == 0 || type.toString() != "EXPLOSION_LARGE") return;
    let np = hypeUser.filter(e => e.distanceTo(particle) < 5);
    if(np.length != 0) cancel(event);
})

//隐藏第二人称,来自 https://www.chattriggers.com/modules/v/NoSelfie 并略改
const keyBindTogglePerspective = new KeyBind(Client.getMinecraft().field_71474_y.field_151457_aa);
let keyBindTogglePerspectivePressed = 0;

register("guiKey",()=>{PerspectiveTrigger.unregister()});
register("guiClosed",()=>{PerspectiveTrigger.register()});

const PerspectiveTrigger = register('tick', () => {
    if(settings.TogglePerspective === 0) return;
    if (Keyboard.isKeyDown(keyBindTogglePerspective.getKeyCode())) {
        if (Client.settings.getSettings().field_74320_O === 1 && keyBindTogglePerspectivePressed++ === 0) 
            Client.settings.getSettings().field_74320_O = 2;
        else if (keyBindTogglePerspectivePressed++ >= settings.TogglePerspective) 
            Client.settings.getSettings().field_74320_O = 2;
    }
    else if (!Keyboard.isKeyDown(keyBindTogglePerspective.getKeyCode()) && keyBindTogglePerspectivePressed)
        keyBindTogglePerspectivePressed = 0;
});

//一键回头
AddData("lookBackKeyBind",0);
const lookBackKey = new KeyBind("一键回头",SavedData.lookBackKeyBind,"BabayzombieAddons - ChatTriggers Module");
let Perspective = Client.settings.getSettings().field_74320_O;
lookBackKey.registerKeyPress(()=>{
    if(Client.settings.getSettings().field_74320_O != 2) Perspective = Client.settings.getSettings().field_74320_O;
    Client.settings.getSettings().field_74320_O = 2;
})
lookBackKey.registerKeyRelease(()=>{
    Client.settings.getSettings().field_74320_O = (Perspective === 2 ? 0 : Perspective);
})

//查看物品配方
AddData("OpenRecipe",0);
const OpenRecipe = new KeyBind("在Skyblock内打开指向物品的合成表",SavedData.OpenRecipe,"BabayzombieAddons - ChatTriggers Module");
register("guiKey", (char,key,gui,event) => {
    if(key != OpenRecipe.getKeyCode()) return;
    const item = getItemFromGui(gui);
    if(!item) return;
    let SBID = getItemSBID(item);
    if(!SBID) return;
    //if(SBID.endsWith("_ITEM")) SBID.replace("_ITEM","");
    ChatLib.command("viewrecipe " + SBID);
})

register("step",()=>{
    SavedData.lookBackKeyBind = lookBackKey.getKeyCode();
    SavedData.OpenRecipe = OpenRecipe.getKeyCode();
}).setDelay(10);


//隐藏距离很近的玩家
register("renderEntity", (entity,pos,tick,event) => {
    if(settings.hideNearPlayer == 0 || !location.inSkyblock) return;
    if(entity.getClassName() != "EntityOtherPlayerMP") return;
    if(entity.getName().includes(' ') || parseInt(getEntityHP(entity).maxhp) == 20) return;
    const entityPos = new Vec3(entity.getX(),entity.getY(),entity.getZ());
    if(entityPos.distance(getPlayerPos()) < settings.hideNearPlayer) cancel(event);
})

//调节Wither Impart音量
const SetHypeVol = register("soundPlay", (pos,name,vol,pitch,cate,event) => {
    if(settings.WitherImpartVol == 10 || name != "random.explode") return;
    try {
        if(!isHype(Player.getHeldItem()) || getPlayerPos().distance(pos) > 1) return;
        cancel(event);
        if(settings.WitherImpartVol == 0) return;
        SetHypeVol.unregister();
        World.playSound(name,settings.WitherImpartVol/10,pitch);
        setTimeout(() => { SetHypeVol.register(); }, 100);
    } catch (error) {}
})

//getfromsacks的Tab补全
const GfsTab = {
    CurrentItems : [],
    CurrentCMDStart : "",
    TabCounter : 0
}

register("guiKey", (char,key,gui,event) => {
    if(!settings.GetfromsacksTabCompletion || !location.inSkyblock || !Client.isInChat()) return;
    if(key != Keyboard.KEY_TAB) {GfsTab.CurrentItems = [];GfsTab.TabCounter = 0;return;};
    let cmd = Client.getCurrentChatMessage();
    if(!(cmd.startsWith("/gfs ") || cmd.startsWith("/getfromsacks "))) return;
    let cmdArray = cmd.split(' ');
    if(GfsTab.CurrentItems.length == 0) {
        for (let ItemName in sack[location.SBProfile]) {
            if(GfsTab.CurrentItems.indexOf(ItemName.removeFormatting()) == -1 && ItemName.removeFormatting().toLowerCase().startsWith(cmdArray.slice(1).join(' ').toLowerCase())) GfsTab.CurrentItems.push(ItemName.removeFormatting());
        }
        GfsTab.CurrentItems.sort();
        GfsTab.CurrentCMDStart = cmdArray[0] + ' ';
    }
    if(GfsTab.CurrentItems.length == 0) {
        if(cmdArray.length > 2 && cmd.endsWith(" ")) {GfsTab.CurrentItems = [1,2,4,9,16,64,128,256,512,576,1152,1728,2240]; GfsTab.CurrentCMDStart = cmdArray.join(' ');}
        else return;
    }
    Client.setCurrentChatMessage(GfsTab.CurrentCMDStart + GfsTab.CurrentItems[GfsTab.TabCounter]);
    let tabMessage = GfsTab.CurrentItems.slice();
    tabMessage[GfsTab.TabCounter] = "§f" + tabMessage[GfsTab.TabCounter] + "§7";
    new Message("§7" + tabMessage.join('§r§7, ')).setChatLineId(MessageID.TabCompletion).chat();
    clearTabCompletionMessage.clearNext();
    if(++GfsTab.TabCounter >= GfsTab.CurrentItems.length) GfsTab.TabCounter = 0;
})

//股票价格计算
register("itemTooltip" ,(lore,item) => {
    if(!location.inSkyblock || location.island != "Hub" || location.location != "Trade Center") return;
    if(Player.getContainer() && Player.getContainer().getName().removeFormatting() != "Stonks Auction") return;
    if(item.getName().removeFormatting() != "Stonks Auction") return;
    lore.forEach((l,i) => {
        if(l.removeFormatting().startsWith("▶ TOP ")) {
            if(!lore[i+1].removeFormatting().includes("m per")) {
                let stack = l.match(/x[0-9]{1,2}/)[0].replace("x","");
                let price = parseInt(lore[i+1].removeFormatting().match(/[0-9,]+ Coins/)[0].replace(/,/g,""));
                addLore(item,lore[i+1] + " §7(" + (price / parseInt(stack.replace("x","")) / 1000000).toFixed(2) + "m per)",lore[i+1].removeFormatting());
            }
        }
    })
})


//Jerry Box开启帮助
register("guiOpened", () => {
    if(!location.inSkyblock || Player.getHeldItem() == null || !getItemSBID(Player.getHeldItem()).startsWith("JERRY_BOX")) return;
    setTimeout(() => {
        if(Player.getContainer() == undefined || Player.getContainer().getName().removeFormatting() != "Open a Jerry Box") return;
        moveMouseToSlot(22);
    }, 50);
})

register("guiMouseClick", (mx,my,button,gui,event) => {
    if(button != 1) return;
    if(!location.inSkyblock || Player.getHeldItem() == null || !getItemSBID(Player.getHeldItem()).startsWith("JERRY_BOX")) return;
    if(Player.getContainer() == undefined || Player.getContainer().getName().removeFormatting() != "Open a Jerry Box") return;
    let item = getItemFromGui(gui);
    if(!item || !item.getName().removeFormatting().endsWith("Jerry Box")) return;
    setTimeout(() => {
        Client.currentGui.close();
    }, 200);
})


//每日奖励消息 中 → 英 这样其他mod就能检测到了
const https = /https:\/\/rewards\.hypixel\.net\/claim-reward\/([A-Za-z0-9]{8})/i;
if (isModLoaded("gravyrewardclaim")) {
register("chat", (link,event) => {
    new Message(`Click the link to visit our website and claim your reward: ${https.exec(link)[0]}`).setRecursive(true).chat();
}).setCriteria("->newLine<-点击链接访问我们的网站并领取奖励：${link}->newLine<-")
register("chat", (link,event) => {
    new Message(`We noticed you haven't claimed your free Daily Reward yet!\nTo choose your reward you have to click the link to visit our website! As a reminder, here's your link for today:  ${https.exec(link)[0]}`).setRecursive(true).chat();
    cancel(event);
}).setCriteria("->newLine<-我们注意到你还没领取你的免费每日奖励！->newLine<-若要选择奖励，你需要点击本链接浏览我们的网站！这是今天的每日奖励链接：  ${link}->newLine<-")
}


//获取当前告示牌选择的行数
let signEditLine = 0;
register("guiKey", (char,keyCode,gui,event) => {
    if(!(isModLoaded("skytils") && gui.toString().includes("GuiEditSign") ? gui.getTileSign() : gui.field_146848_f)) return;
    switch (keyCode) {
        case Keyboard.KEY_UP:
            if(--signEditLine < 0) signEditLine = 3;
            break;
        case Keyboard.KEY_DOWN:
        case Keyboard.KEY_RETURN:
            if(++signEditLine > 3) signEditLine = 0;
            break;
        default:
            return;
    }
})
register("guiOpened", () => {signEditLine = 0;})

//告示牌  剪贴 复制 粘贴 删除
register("guiKey", (char,keyCode,gui,event) => {
    if(!settings.betterSignEdit) return;
    if(!Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) return;
    let sign = isModLoaded("skytils") && gui.toString().includes("GuiEditSign") ? gui.getTileSign() : gui.field_146848_f;  //gui.tileSign;
    if(!sign) return;
    let texts = sign.field_145915_a;  //tileSign.signText;  [MCIChatComponent]
    switch (keyCode) {
        case Keyboard.KEY_X:  //剪贴
            copyToClipboard(texts[signEditLine].func_150260_c());
            texts[signEditLine] = new TextComponent("").chatComponentText;
            break;
        case Keyboard.KEY_C:  //复制
            copyToClipboard(texts[signEditLine].func_150260_c());
            break;
        case Keyboard.KEY_V:  //粘贴
            let clip = getClipboard();
            if(!clip) return;
            texts[signEditLine] = new TextComponent(texts[signEditLine].func_150260_c() + clip).setFormatted(false).chatComponentText;
            break;
        case Keyboard.KEY_DELETE:  //删除
            texts[signEditLine] = new TextComponent("").chatComponentText;
            break;
        default:
            return;
    }
})


//ah快速上架
const neu = isModLoaded("notenoughupdates") ? Java.type("io.github.moulberry.notenoughupdates.NotEnoughUpdates") : undefined;
const QuickAuction = {
    RegExp : {
        itemName : /Item: (.+)/,
        duration : /Auction duration: (.+)/,
        price : /Item price: ([0-9,]+) coins/,
    },
    
    status : "",
    items : {},
    CurrentItem : null,
    CurrentItemName : "",
    guiClose : 0,
    lastItemSlotId : -1,

    clearItemTrigger : register("step", () => {
        for (let itemName in QuickAuction.items) {
            if (QuickAuction.items[itemName].timestamp + 10 * 60 * 1000 < Date.now()) 
                delete QuickAuction.items[itemName];
        }
    }).setDelay(60),
    
    guiClickTrigger : register("guiMouseClick", (mx,my,button,gui,event) => {
        if(!settings.quickAuction || !location.inSkyblock) return;

        if(isModLoaded("skytils") && gui.toString().includes("GuiEditSign") ? gui.getTileSign() : gui.field_146848_f) {
            let sign = isModLoaded("skytils") && gui.toString().includes("GuiEditSign") ? gui.getTileSign() : gui.field_146848_f;
            let signText = sign.field_145915_a;
            switch (QuickAuction.status) {
                case "输入价格":
                    if(QuickAuction.CurrentItem != null) {
                        if(signText[0].func_150260_c() == "")
                         signText[0] = new TextComponent(QuickAuction.CurrentItem.price.replace(/,/g,"")).chatComponentText;
                    } else {
                        if(signText[0].func_150260_c() == "") {
                            ChatLib.chat(`§b§l[BZA]§r §c请手动为物品 §r${QuickAuction.CurrentItemName} §r§c输入价格`);
                            cancel(event);
                            return;
                        }
                    }
                    QuickAuction.status = "准备上架";
                    Player.getPlayer().func_175159_q();
                    break;
                case "输入时间":
                    if(QuickAuction.CurrentItem != null) {
                        if(signText[0].func_150260_c() == "")
                         signText[0] = new TextComponent(parseInt(QuickAuction.CurrentItem.duration) * (QuickAuction.CurrentItem.duration.includes("Days") ? 24 : 1)).chatComponentText;
                    } else {
                        if(signText[0].func_150260_c() == "")
                         signText[0] = new TextComponent("336").chatComponentText;
                    }
                    QuickAuction.status = "设定价格";
                    Player.getPlayer().func_175159_q();
                    break;
            }
            return;
        }

        let container = Player.getContainer();
        if( !container || !(
            container.getName().removeFormatting().endsWith("Auction House") ||
            container.getName().removeFormatting() == "Create BIN Auction" ||
            container.getName().removeFormatting() == "Confirm BIN Auction" ||
            container.getName().removeFormatting() == "Auction Duration" ||
            container.getName().removeFormatting() == "BIN Auction View"
        ) ) return;
        let clickedItem = getItemFromGui(gui);
        if(!clickedItem) return;
        let clickedItemName = clickedItem.getName().removeFormatting();

        if(container.getName().removeFormatting() == "Auction Duration") {
            if(clickedItemName == "Custom Duration") {
                QuickAuction.status = "输入时间";
            } else if(["1 Hour","6 Hour","12 Hour","24 Hour","2 Days"].indexOf(clickedItemName) != -1) {
                QuickAuction.status = "设定价格";
            }
            return;
        }

        if(container.getName().removeFormatting() == "BIN Auction View") {
            switch (clickedItemName) {
                case "Go Back":
                    QuickAuction.status = "等待物品";
                    break;
                case "Close":
                    QuickAuction.status = "";
                    QuickAuction.CurrentItem = null;
                    QuickAuction.CurrentItemName = "";
                    QuickAuction.renderItemIntoGuiTrigger.unregister();
                    QuickAuction.guiClose = 0;
                    QuickAuction.lastItemSlotId = -1;
                    break;
            }
            return;
        }

        switch (true) {
            case clickedItemName == "Create BIN Auction":
                let lore = clickedItem.getLore();
                let itemName = lore.filter(l => l.match(QuickAuction.RegExp.itemName))[0].match(QuickAuction.RegExp.itemName)[1];
                let itemDuration = lore.filter(l => l.removeFormatting().match(QuickAuction.RegExp.duration))[0].removeFormatting().match(QuickAuction.RegExp.duration)[1];
                let itemPrice = lore.filter(l => l.removeFormatting().match(QuickAuction.RegExp.price))[0].removeFormatting().match(QuickAuction.RegExp.price)[1];
                QuickAuction.items[itemName] = {timestamp : Date.now(), duration : itemDuration, price : itemPrice};
                QuickAuction.CurrentItem = QuickAuction.items[itemName];
                QuickAuction.status = "上架确认";
                break;

            case clickedItemName == "Confirm" && container.getName().removeFormatting() == "Confirm BIN Auction":
                QuickAuction.status = "正在上架";
                break;
            case clickedItemName == "Cancel" && container.getName().removeFormatting() == "Confirm BIN Auction":
                QuickAuction.status = "准备上架";
                break;

            case clickedItemName.startsWith("Item price: "):
                QuickAuction.status = "输入价格";
                break;
            case clickedItemName.startsWith("Duration: "):
                QuickAuction.status = "选择时间";
                break;
            case clickedItemName == "AUCTION FOR ITEM:":
                QuickAuction.status = "";
                QuickAuction.CurrentItem = null;
                QuickAuction.CurrentItemName = "";
                break;
            case clickedItemName == "Click an item in your inventory":
            case clickedItemName == "Go Back":
                break;

            default:
                if(!gui.getSlotUnderMouse()) return;
                let slotId = gui.getSlotUnderMouse().field_75222_d;
                if( !(
                    container.getName().removeFormatting() == "Create BIN Auction" && slotId >= 54 || 
                    container.getName().removeFormatting().endsWith("Auction House") && slotId >= 36
                ) ) return;

                if(container.getName().removeFormatting().endsWith("Auction House")) {
                    QuickAuction.status = "开始上架";
                    QuickAuction.lastItemSlotId = slotId + 18;
                } else {
                    QuickAuction.lastItemSlotId = slotId;
                    QuickAuction.status = "点击物品";
                    QuickAuction.renderItemIntoGuiTrigger.register();
                }
                break;
        }
    }),

    guiKeyTrigger : register("guiKey", (char,key,gui,event) => {
        if(!settings.quickAuction || !location.inSkyblock || !isModLoaded("skytils")) return;
        if(QuickAuction.status != "输入价格") return;
        if(key != Keyboard.KEY_RETURN && key != Keyboard.KEY_NUMPADENTER) return;
        let sign = gui.toString().includes("GuiEditSign") ? gui.getTileSign() : gui.field_146848_f;
        if(!sign) return;
        QuickAuction.status = "准备上架";
    }),

    guiOpenTrigger : register("guiOpened", () => {
        if(!settings.quickAuction || !location.inSkyblock) return;
        QuickAuction.renderItemIntoGuiTrigger.register();
        QuickAuction.guiClose = 0;
        if(!QuickAuction.CurrentItem) return;
        setTimeout(() => {
            let gui = mc.field_71462_r;
            if(!gui) return;
            let sign = isModLoaded("skytils") && gui.toString().includes("GuiEditSign") ? gui.getTileSign() : gui.field_146848_f;
            if(!sign) return;
            let signText = sign.field_145915_a;
            if(signText[0].func_150260_c() != "") return;
            switch (QuickAuction.status) {
                case "输入价格":
                    signText[0] = new TextComponent(QuickAuction.CurrentItem.price.replace(/,/g,"")).chatComponentText;
                    break;
                case "输入时间":
                    signText[0] = new TextComponent(parseInt(QuickAuction.CurrentItem.duration) * (QuickAuction.CurrentItem.duration.includes("Days") ? 24 : 1)).chatComponentText;
                    break;
            }
        }, 50);
    }),

    renderItemIntoGuiTrigger : register("renderItemIntoGui", (item,x,y,event) => {
        if(!settings.quickAuction || !location.inSkyblock) return;
        if(isModLoaded("skytils") && mc.field_71462_r.toString().includes("GuiEditSign") ? mc.field_71462_r.getTileSign() : mc.field_71462_r.field_146848_f) return;

        let container = Player.getContainer();
        if( !( (container.getName().removeFormatting() == "Confirm BIN Auction" && item.getName().removeFormatting() == "Cancel")
            || (container.getName().removeFormatting() == "BIN Auction View" && item.getName().removeFormatting() == "Close")
            || item.getName().removeFormatting() == "Go Back"
        ) ) return;

        if( !container || !(
            container.getName().removeFormatting() == "Create BIN Auction" ||
            container.getName().removeFormatting() == "Confirm BIN Auction" ||
            container.getName().removeFormatting() == "Auction Duration" ||
            container.getName().removeFormatting() == "BIN Auction View"
        ) ) return;
        
        switch (QuickAuction.status) {
            case "等待物品":
                if(QuickAuction.lastItemSlotId != -1) {
                    moveMouseToSlot(QuickAuction.lastItemSlotId);
                    QuickAuction.lastItemSlotId = -1;
                }
                break;
            case "点击物品":
                let itemOnAuction = container.getStackInSlot(29);
                if(itemOnAuction.getName().startsWith("§c")) return;
                QuickAuction.status = "开始上架";
            case "开始上架":
                setTimeout(() => {
                    if(container.getName().removeFormatting() == "Create BIN Auction") {
                        let itemName = container.getStackInSlot(29).getLore().filter(l => l.match(QuickAuction.RegExp.itemName))[0].match(QuickAuction.RegExp.itemName)[1];
                        let itemOnAuction = container.getStackInSlot(13);
                        if(itemOnAuction && GetAttributesFrom(itemOnAuction) === null) {
                            if(QuickAuction.items[itemName]) QuickAuction.CurrentItem = QuickAuction.items[itemName];
                            else if(isModLoaded("notenoughupdates")){
                                let internalname = neu.INSTANCE.manager
                                .createItemResolutionQuery()
                                .withCurrentGuiContext()
                                .withItemStack(itemOnAuction.getItemStack())
                                .resolveInternalName();
                                let lowestBin = neu.INSTANCE.manager.auctionManager.getLowestBin(internalname);
                                if(lowestBin > 0) QuickAuction.CurrentItem = {price: (--lowestBin).toString().replace(/\B(?=(?:\d{3})+\b)/g, ','), duration: "2 Days"};
                            }
                        }
                        QuickAuction.CurrentItemName = itemName;
                        moveMouseToSlot(QuickAuction.CurrentItem != null && QuickAuction.CurrentItem.duration == "6 Hours" ? 31 : 33);
                    }
                }, 50);
                break;
            case "准备上架":
                moveMouseToSlot(29);
                break;
            case "上架确认":
                moveMouseToSlot(11);
                break;
            case "设定价格":
                moveMouseToSlot(31);
                break;
            case "选择时间":
                if(QuickAuction.CurrentItem == null || container.getName().removeFormatting() != "Auction Duration") return;
                switch (QuickAuction.CurrentItem.duration) {
                    case "1 Hour":
                        moveMouseToSlot(10);
                        break;
                    case "6 Hours":
                        moveMouseToSlot(11);
                        break;
                    case "12 Hours":
                        moveMouseToSlot(12);
                        break;
                    case "24 Hours":
                        moveMouseToSlot(13);
                        break;
                    case "2 Days":
                        moveMouseToSlot(14);
                        break;
                    default:
                        moveMouseToSlot(16);
                        break;
                }
                break;
            case "上架完成":
                moveMouseToSlot(49);
                break
        }

        QuickAuction.renderItemIntoGuiTrigger.unregister();
    }).unregister(),

    chatTrigger : register("chat", () => {
        if(!settings.quickAuction || !location.inSkyblock) return;

        QuickAuction.status = "上架完成";
        QuickAuction.CurrentItem = null;
        QuickAuction.CurrentItemName = "";
    }).setCriteria(/BIN Auction started for .+!/),

    guiCloseTrigger : register("guiClosed", () => {
        QuickAuction.guiClose = Date.now();
    }),

    stepTrigger : register("step", () => {
        if(QuickAuction.guiClose && QuickAuction.guiClose + 1000 < Date.now() && !mc.field_71462_r) {
            QuickAuction.status = "";
            QuickAuction.CurrentItem = null;
            QuickAuction.CurrentItemName = "";
            QuickAuction.renderItemIntoGuiTrigger.unregister();
            QuickAuction.guiClose = 0;
            QuickAuction.lastItemSlotId = -1;
        }
    }).setDelay(1),
    
    renderGuiTrigger : register("guiRender", (mx,my,gui) => {
        if(!settings.quickAuction || !location.inSkyblock) return;
        
        if(!QuickAuction.status) return;
        let sign = isModLoaded("skytils") && gui.toString().includes("GuiEditSign") ? gui.getTileSign() : gui.field_146848_f;
        let isSign = sign != undefined;
        let showString = `§6§l[BZA] §b快速上架\n§b当前状态§7: §a${QuickAuction.status}` +
         (QuickAuction.CurrentItemName ? `\n§b正在上架§7: §r${QuickAuction.CurrentItemName}` +
         (QuickAuction.CurrentItem ? `\n§b上架价格§7: §a${QuickAuction.CurrentItem.price}\n§b上架时间§7: §a${QuickAuction.CurrentItem.duration}\n§c请确认当前价格为您想要的价格` +
         (isSign ? "\n§b点击任意处填入价格/时间" : '') : '') : '');
        DrawString(showString,isSign ? Renderer.screen.getWidth() / 2 + 50 : gui.guiLeft + 200, isSign ? 50 : gui.guiTop + 8,Renderer.screen.getScale() * 0.6,true);
    })
}


//扫水果
const FruitDigging = {
    fruitsList : {
        "ewogICJ0aW1lc3RhbXAiIDogMTcxODIwMzE5MzY5OCwKICAicHJvZmlsZUlkIiA6ICIyMjAwZjYzOWI1YTU0YzM2YjA4ZThiNjZhNDNjNmJjNCIsCiAgInByb2ZpbGVOYW1lIiA6ICJCYXVvSmxlVCIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9jOTJiMDk5YTYyY2QyZmJmOGFkYTA5ZGVjMTQ1Yzc1ZDdmZGE0ZGM1N2I5NjhiZWEzYThmYTExZTM3YWE0OGIyIgogICAgfQogIH0KfQ==" : "Cherry",
        "ewogICJ0aW1lc3RhbXAiIDogMTcxOTMyMDg4MTU1MCwKICAicHJvZmlsZUlkIiA6ICJiMTM1MDRmMjMxOGI0OWNjYWFkZDcyYWVhYmMyNTQ1MCIsCiAgInByb2ZpbGVOYW1lIiA6ICJUeXBrZW4iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTdlYTI3OGQ2MjI1YzQ0N2M1OTQzZDY1Mjc5OGQwYmJiZDE0MTg0MzRjZThjNTRjNTRmZGFjNzk5OTRkZGQ2YyIKICAgIH0KICB9Cn0=" : "Apple",
        "ewogICJ0aW1lc3RhbXAiIDogMTcxOTMyMDk0MjUyNSwKICAicHJvZmlsZUlkIiA6ICI1ZjU5NmViY2JlOTQ0NmQxYmI0M2JlNGYzZjRiOGJlNSIsCiAgInByb2ZpbGVOYW1lIiA6ICJUZWlsMHNzIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2FjMjY4ZDM2YzJjNjA0N2ZmZWVjMDAxMjQwOTYzNzZiNTZkYmI0ZDc1NmE1NTMyOTM2M2ExYjI3ZmNkNjU5Y2QiCiAgICB9CiAgfQp9" : "Durian",
        "ewogICJ0aW1lc3RhbXAiIDogMTcxODIwMzIxNTc3NiwKICAicHJvZmlsZUlkIiA6ICJmZmU5MzczY2YyMDM0OWFhYTJlN2NiYzJkZmY2M2I5MyIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWxvblR1bmExIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzEwY2ViMTQ1NWI0NzFkMDE2YTlmMDZkMjVmNmU0NjhkZjlmY2YyMjNlMmMxZTQ3OTViMTZlODRmY2NhMjY0ZWUiCiAgICB9CiAgfQp9" : "Coconut",
        "ewogICJ0aW1lc3RhbXAiIDogMTcxOTMyMDk5NTI0OCwKICAicHJvZmlsZUlkIiA6ICI4YWFlYTdlYjViOWM0ZWEwODUxNWU3MDhhZGIxODBkNyIsCiAgInByb2ZpbGVOYW1lIiA6ICJNYVBhODA3MTEiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWZlNGVmODNiYWYxMDVlOGRlZTZjZjAzZGZlNzQwN2YxOTExYjNiOTk1MmM4OTFhZTM0MTM5NTYwZjI5MzFkNiIKICAgIH0KICB9Cn0=" : "Watermelon",
        "ewogICJ0aW1lc3RhbXAiIDogMTcxOTMyMDk4MDg4NywKICAicHJvZmlsZUlkIiA6ICJiMmQ4MTA2YTJjM2Y0ZTY4ODA0ODkzOWU0NGM1NmUyMiIsCiAgInByb2ZpbGVOYW1lIiA6ICJSZWdoeGQiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDA4MjRkMTgwNzkwNDJkNTc2OWYyNjRmNDQzOTRiOTViOWI5OWNlNjg5Njg4Y2MxMGM5ZWVjM2Y4ODJjY2MwOCIKICAgIH0KICB9Cn0=" : "Pomegranate",
        "ewogICJ0aW1lc3RhbXAiIDogMTcxOTMyMDkyODM3MiwKICAicHJvZmlsZUlkIiA6ICJmNzg5OWI1ZGEzZGM0ZTY0YmFlM2QyMmYzMWFjMzBhZSIsCiAgInByb2ZpbGVOYW1lIiA6ICJwaXhlbGJsb2IxMjEyIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzNjYzc2MWJjYjA1Nzk3NjNkOWI4YWI2YjdiOTZmYTc3ZWI2ZDk2MDVhODA0ZDgzOGZlYzM5ZTdiMjVmOTU1OTEiCiAgICB9CiAgfQp9" : "Dragonfruit",
        "ewogICJ0aW1lc3RhbXAiIDogMTcxOTMyMDk2NDE1NSwKICAicHJvZmlsZUlkIiA6ICI4ZTFjZTM2ZGE2Mzk0ZjgwOTFmZjZjYTZiZTNhZTA5NSIsCiAgInByb2ZpbGVOYW1lIiA6ICJGdWxsY3JlbiIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9mMzYzYTYyMTI2YTM1NTM3ZjgxODkzNDNhMjI2NjBkZTc1ZTgxMGM2YWMwMDRhN2QzZGE2NWYxYzA0MGE4MzkiCiAgICB9CiAgfQp9" : "Mango",
        "ewogICJ0aW1lc3RhbXAiIDogMTYyNDU0NjA4NjAxNiwKICAicHJvZmlsZUlkIiA6ICI0NWY3YTJlNjE3ODE0YjJjODAwODM5MmRmN2IzNWY0ZiIsCiAgInByb2ZpbGVOYW1lIiA6ICJfSnVzdERvSXQiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTc2YTI4MTFkMWUxNzZhMDdiNmQwYTY1N2I5MTBmMTM0ODk2Y2UzMDg1MGY2ZTgwYzdjODM3MzJkODUzODFlYSIKICAgIH0KICB9Cn0=" : "Bomb",
        "ewogICJ0aW1lc3RhbXAiIDogMTcxODIwMzIzMzA1NiwKICAicHJvZmlsZUlkIiA6ICIxODA1Y2E2MmM0ZDI0M2NiOWQxYmY4YmM5N2E1YjgyNCIsCiAgInByb2ZpbGVOYW1lIiA6ICJSdWxsZWQiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDA3YjI3NWQyOGI5MjdiMWJmN2Y2ZGQ5ZjQ1ZmJkYWQyYWY4NTcxYzU0YzhmMDI3ZDFiZmY2OTU2ZmJmM2MxNiIKICAgIH0KICB9Cn0=" : "Rum",
    },

    digLoc : null,
    fruits : [],
    treasures : [],
    bombs : [],

    isInArea(loc) {
        return loc.getX() >= -112 && loc.getX() <= -105 && loc.getZ() >= -11 && loc.getZ() <= -4 && loc.getY() >= 72 && loc.getY() <= 75;
    },

    hitBlock : register("hitBlock", (block,event) => {
        if(!settings.FruitDiggingHelper || !location.inSkyblock || location.location != "Carnival") return;
        if(!FruitDigging.isInArea(block)) return;
        FruitDigging.digLoc = {x: block.getX(), z: block.getZ()};
    }),

    itemRender : register("renderEntity", (entity,position,ticks,event) => {
        if(!settings.FruitDiggingHelper || !location.inSkyblock || location.location != "Carnival") return;
        if(entity.getClassName() != "EntityItem") return;
        let pos = entity.getPos();
        if(!FruitDigging.isInArea(pos)) return;
        let item = entity.entity.func_92059_d();
        if(!item || new Item(item).getRegistryName() != "minecraft:skull") return;
        let fruitName = FruitDigging.fruitsList[getskulltextures(item)];
        if(!fruitName) return;
        let isDigged = World.getBlockAt(Math.floor(pos.getX())-1,72,Math.floor(pos.getZ())-1).getType().getRegistryName() != "minecraft:sand";
        FruitDigging.fruits.forEach((f,i,a) => {
            if(f.x == Math.floor(pos.getX()) && f.z == Math.floor(pos.getZ())) a = a.splice(i,1);
        })
        FruitDigging.fruits.push({x: Math.floor(pos.getX()), z: Math.floor(pos.getZ()), s: `§${isDigged ? "a" : "e"}${fruitName}`});
    }),

    treasureChat : register("chat", (fruit) => {
        if(FruitDigging.digLoc == null) return;
        FruitDigging.treasures.push({x: FruitDigging.digLoc.x, z: FruitDigging.digLoc.z, s: `§e附近有 ${fruit}`});
        FruitDigging.digLoc = null;
    }).setCriteria(/TREASURE! There is a[n]? ([a-zA-Z]+) nearby./i),
        
    anchorChat : register("chat", () => {
        if(FruitDigging.digLoc == null) return;
        FruitDigging.treasures.push({x: FruitDigging.digLoc.x, z: FruitDigging.digLoc.z, s: `§e附近没有水果`});
        FruitDigging.digLoc = null;
    }).setCriteria(/(ANCHOR|TREASURE)! There are no fruits nearby!/i),

    bombChat : register("chat", (bombs) => {
        if(FruitDigging.digLoc == null) return;
        FruitDigging.bombs.push({x: FruitDigging.digLoc.x, z: FruitDigging.digLoc.z, s: `§c附近有${bombs}个炸弹`});
        FruitDigging.digLoc = null;
    }).setCriteria(/MINES! There are ([0-9]+) bomb[s]? hidden nearby./i),
    
    resetChat : register("chat", () => {
        FruitDigging.fruits = [];
        FruitDigging.treasures = [];
        FruitDigging.bombs = [];
        FruitDigging.digLoc = null;
    }).setCriteria(/(                               Fruit Digging|\[NPC\] Carnival Pirateman: Here's yer shovel, then.)/i),

    resetWorldload : register("worldLoad", () => {
        FruitDigging.fruits = [];
        FruitDigging.treasures = [];
        FruitDigging.bombs = [];
        FruitDigging.digLoc = null;
    }),

    render : register("renderWorld", (ticks) => {
        if(!settings.FruitDiggingHelper || !location.inSkyblock || location.location != "Carnival") return;
        FruitDigging.bombs.forEach(e => {
            Tessellator.drawString(e.s,e.x+0.5,74.7,e.z+0.5,0,false,0.02,false);
        })
        FruitDigging.treasures.forEach(e => {
            Tessellator.drawString(e.s,e.x+0.5,74.5,e.z+0.5,0,false,0.02,false);
        })
        FruitDigging.fruits.forEach(e => {
            Tessellator.drawString(e.s,e.x-0.5,74.3,e.z-0.5,0,false,0.02,false);
        })
    })
}

//没有雾
register(net.minecraftforge.client.event.EntityViewRenderEvent.FogDensity, event => {
    if(settings.noFog == 0 || !(settings.noFog != 2 || location.inSkyblock)) return;
    GlStateManager.func_179102_b(0.01);
    GlStateManager.func_179153_c(0.0);
    event.density = 0.0;
    event.setCanceled(true);
}).setPriority(Priority.LOWEST)


//修改染色防具的SBID
register("packetReceived", (packet,event) => {
    if(!settings.dyedArmor || !location.inSkyblock) return;
    let armorItemStack = packet instanceof net.minecraft.network.play.server.S04PacketEntityEquipment ? packet.func_149390_c() : packet.func_149174_e();
    if(armorItemStack == null) return;
    let armor = new Item(armorItemStack);
    if(armor == null) return;
    let sbid = getItemSBID(armor);
    if(sbid == null || sbid.startsWith("DYED_")) return;
    let dye = armor.getNBT()?.getCompoundTag("tag")?.getCompoundTag("ExtraAttributes")?.getString("dye_item");
    if(dye == null || dye == "") return;
    armor.getNBT().getCompoundTag("tag").getCompoundTag("ExtraAttributes").setString("id",`DYED_${sbid}`);
}).setFilteredClasses([net.minecraft.network.play.server.S04PacketEntityEquipment,net.minecraft.network.play.server.S2FPacketSetSlot])


//清实体
register("step", () => {
    if(settings.clearEntity == 0 || !location.inSkyblock) return;
    if([1,4,5,7].indexOf(settings.clearEntity) != -1) {
        let players = World.getWorld().field_73010_i;
        players.forEach(e => {
            if(e.field_70128_L) World.getWorld().func_72900_e(e);
            if(e.field_70165_t == 0 && e.field_70163_u == 0 && e.field_70161_v == 0) World.getWorld().func_73028_b(e.func_145782_y());
        });
    }
    if([3,5,6,7].indexOf(settings.clearEntity) != -1) {
        World.getAllEntitiesOfType(net.minecraft.entity.item.EntityArmorStand).filter(e => e.isInvisible() && e.getEntity().func_95999_t() == "").forEach(e => {
            for (let i = 0; i < 5; i++) {
                if(e.getEntity().func_71124_b(i) != null) return;
            }
            World.getWorld().func_73028_b(e.getEntity().func_145782_y());
        })
    }
}).setDelay(30)


//bits shop
if(neu) register(net.minecraftforge.event.entity.player.ItemTooltipEvent, event => {
    if(!eventSettings.BitsShopPrice) return;
    let menuName = Player.getContainer()?.getName().removeFormatting();
    if(menuName != "Community Shop" && !menuName.startsWith("Bits Shop")) return;
    let lore = "";
    for (let key in event.toolTip) {
        lore += event.toolTip[key] + "\n";
    }
    if(!lore.includes("§eClick to trade!")) return;
    let price = lore.match(/§5§o§7Cost\n§5§o§b([0-9,]+) Bits/);
    if(!price) return;
    let bitsPrice = parseInt(price[1].replace(/,/,''));
    let internalname = neu.INSTANCE.manager
    .createItemResolutionQuery()
    .withCurrentGuiContext()
    .withItemStack(event.itemStack)
    .resolveInternalName();
    let lowestBin = neu.INSTANCE.manager.auctionManager.getLowestBin(internalname);
    if(lowestBin == -1) {
        let bazaarInfo = neu.INSTANCE.manager.auctionManager.getBazaarInfo(internalname);
        if(bazaarInfo.has("curr_sell")) lowestBin = bazaarInfo.get("curr_sell").getAsFloat();
    };
    ListFix.add(event,"toolTip","§bCoins/Bits: §a" + (lowestBin > 0 ? (lowestBin / bitsPrice).toFixed(2) : "N/A"));
})


/**
 * 进行一个NEU Repo 的下载和更新
 */
export function updateNEUREPO() {
    if(!FileLib.exists("./config/notenoughupdates")) return;
    urlToFile("https://codeload.github.com/NotEnoughUpdates/NotEnoughUpdates-REPO/zip/refs/heads/prerelease","./config/ChatTriggers/modules/BabyzombieAddons/NEUREPO.zip").then(e => {
        new Message("§6§l[BZA] §a下载完成,正在删除老repo文件夹").setChatLineId(MessageID.UpdateNeuRepo).chat();
        FileLib.deleteDirectory("./config/notenoughupdates/repo");
        new Message("§6§l[BZA] §a正在解压压缩包").setChatLineId(MessageID.UpdateNeuRepo).chat();
        FileLib.unzip(e,"./config/notenoughupdates");
        FileLib.delete(e);
        new File("./config/notenoughupdates/NotEnoughUpdates-REPO-prerelease").renameTo(new File("./config/notenoughupdates/repo"));
        new Message("§6§l[BZA] §aNEUREPO 更新完成").setChatLineId(MessageID.UpdateNeuRepo).chat();
        if(isModLoaded("notenoughupdates")) ChatLib.command("neureloadrepo",true);
    }).catch(error => {new Message("§6§l[BZA] §4下载失败§r \n§c" + error).setChatLineId(MessageID.UpdateNeuRepo).chat()});
}
//Highlight Attributes
register("renderItemOverlayIntoGui", HighlightAttributes);

function HighlightAttributes(item, x, y, event) {
    if (!location.inSkyblock || !AttributeHighlightSettings.AttributeHighlight) return;

    const attributes = GetAttributesFrom(item);
    if (!attributes) return;

    const att1 = AttributeHighlightSettings.AttributeHighlightAtt1.trim().toLowerCase().replace(/ /g, '_');
    const att2 = AttributeHighlightSettings.AttributeHighlightAtt2.trim().toLowerCase().replace(/ /g, '_');

    if (!att1 && !att2) return;

    const itemAttributes = Object.keys(attributes);

    const match1 = att1 !== '' && itemAttributes.includes(att1);
    const match2 = att2 !== '' && itemAttributes.includes(att2);

    let highlight = false;
    if (AttributeHighlightSettings.AttributeHighlightMode === 0) { // Match Any
        highlight = (att1 && match1) || (att2 && match2);
    } else { // Match Both
        if (att1 && att2) {
            highlight = match1 && match2;
        } else if (att1) {
            highlight = match1;
        } else {
            highlight = match2;
        }
    }
    
    if (highlight) {
        const color = AttributeHighlightSettings.AttributeHighlightColor;
        Renderer.translate(0, 0, 1);
        Renderer.drawRect(color.getRGB(), x, y, 16, 16);
    }
}